﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml.Linq;
using System.Xml;
using CopySniffer.Search.Boss.Properties;

namespace CopySniffer.Search.Boss
{
    public class BossSearchProvider : ISearchProvider
    {
        #region ISearchProvider Members

        public IEnumerable<SearchResult> Search(SearchInfo searchInfo)
        {
            HttpWebRequest request = WebRequest.Create(GetRequestUri(searchInfo)) as HttpWebRequest;

            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                XmlReader reader = XmlReader.Create(response.GetResponseStream());
                XDocument doc = XDocument.Load(reader);
                var q = from e in doc.Descendants(GetXName("result"))
                        select new SearchResult() 
                        { 
                            Abstract = e.Element(GetXName("abstract")).Value, 
                            Date = GetDateTimeValue(e.Element(GetXName("date")).Value), 
                            Url = e.Element(GetXName("url")).Value, 
                            Title = e.Element(GetXName("title")).Value 
                        };

                return q.ToList();
            }
        }

        private static string GetRequestUri(SearchInfo searchInfo)
        {
            StringBuilder uriBuilder = new StringBuilder(Properties.Resources.BossUri);
            bool isFirst = true;
            foreach (var token in searchInfo.Tokens)
            {
                uriBuilder.AppendFormat("{1}{2}{0}{1}",
                    token.Contents,
                    token.ExactMatch ? "\"" : String.Empty,
                    token.Negated ? "-" : isFirst ? String.Empty : "+");
            }

            uriBuilder.AppendFormat("?appid={0}&format=xml", Resources.AppId);
            string requestUri = uriBuilder.ToString();
            return requestUri;
        }

        #endregion

        private static XName GetXName(string elementName)
        {
            return XName.Get(elementName, Resources.BossAnswerNamespaceName);
        }

        private static DateTime? GetDateTimeValue(string text)
        {
            if (!String.IsNullOrEmpty(text))
            {
                DateTime realDateTime;
                if (DateTime.TryParse(text, out realDateTime))
                {
                    return realDateTime;
                }
            }

            return null;
        }
    }
}
